package com.qingzhuge.controller.security;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.AsymmetricCrypto;
import com.qingzhuge.autoconfigure.QingTingProperties;
import com.qingzhuge.autoconfigure.SecurityProperties;
import com.qingzhuge.cache.CacheChannel;
import com.qingzhuge.cache.support.CacheObject;
import com.qingzhuge.common.utils.WebUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

/**
 * @author : zero.xiao
 * @description :
 * @date :2019-08-13 11:16
 * @modified : 存储用户前后端数据交互加密密钥
 */
@Component
public class ControllerSecurityBody {
    private String region = "api_data_encryption";

    @Resource
    private CacheChannel channel;

    @Resource
    private QingTingProperties properties;

    private String getKey(){
        HttpSession session = WebUtil.getSession();
        assert session != null;
        return session.getId();
    }

    /**
     * 从缓存中获取 RsaKey，如果不存在就生存一个新的放入缓存
     * @return RsaKey
     */
    public RsaKey get(){
        String key = getKey();
        if (StringUtils.isEmpty(key)){
            return null;
        }
        RsaKey value;
        CacheObject<Object> cacheObject = channel.get(region,key,true);
        if (null != cacheObject){
            Object cacheValue = cacheObject.getValue();
            if (cacheValue instanceof RsaKey){
                value = (RsaKey) cacheValue;
            }else{
                value = createKey();
            }
        }else{
            value = createKey();
        }
        return value;
    }

    private RsaKey createKey(){
        String key = getKey();
        if (StringUtils.isNotEmpty(key)){
            AsymmetricCrypto crypto = SecureUtil.rsa().initKeys();
            RsaKey rsaKey = RsaKey.of(crypto.getPrivateKeyBase64(),crypto.getPublicKeyBase64());
            SecurityProperties security = properties.getSecurity();
            Long expiration = security.getExpiration();
            channel.set(region,key,rsaKey,expiration,true);
            return rsaKey;
        }
        return null;
    }

    /**是否开户数据加密*/
    public boolean isEncrypt(){
        return properties != null && properties.getSecurity().isOpenEncrypt();
    }
}
